package com.example.service;

import com.example.config.LoginConfig;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 登录服务
 * 职责：处理需要登录的网站
 * 功能：
 * - 检测是否需要登录
 * - 执行登录操作
 * - 管理登录状态
 */
@Service
public class LoginService {
    private static final Logger logger = LoggerFactory.getLogger(LoginService.class);
    private static final String LOG_DIR = "./logs";
    private static final String LOGIN_FAIL_DIR = "./logs/log_failures";
    
    private final LoginConfig loginConfig;
    private final Map<String, Map<String, String>> cookies = new ConcurrentHashMap<>();
    private final Map<String, Boolean> loginStatus = new ConcurrentHashMap<>();
    
    @Autowired
    public LoginService(LoginConfig loginConfig) {
        this.loginConfig = loginConfig;
        createLogDirectory();
    }

    private void createLogDirectory() {
        File logDir = new File(LOG_DIR);
        File loginFailDir = new File(LOGIN_FAIL_DIR);
        if (!logDir.exists()) {
            logDir.mkdirs();
        }
        if (!loginFailDir.exists()) {
            loginFailDir.mkdirs();
        }
    }

    /**
     * 记录登录信息到文件
     */
    private void recordLoginInfo(Document doc, String url) {
        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String filename = "login_info_" + timestamp + ".txt";
        File file = new File(LOGIN_FAIL_DIR, filename);
        
        try (PrintWriter writer = new PrintWriter(
                new OutputStreamWriter(
                    new FileOutputStream(file), 
                    StandardCharsets.UTF_8))) {
            
            writer.println("=== 登录信息记录 ===");
            writer.println("时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            writer.println("URL: " + url);
            writer.println("\n=== 页面分析 ===");
            
            // 记录页面标题
            writer.println("页面标题: " + doc.title());
            
            // 记录页面中的表单
            Elements forms = doc.select("form");
            if (!forms.isEmpty()) {
                writer.println("\n发现表单: " + forms.size() + " 个");
                for (int i = 0; i < forms.size(); i++) {
                    Element form = forms.get(i);
                    writer.println("\n表单 #" + (i + 1) + ":");
                    writer.println("Action: " + form.attr("action"));
                    writer.println("Method: " + form.attr("method"));
                    
                    // 记录输入框
                    Elements inputs = form.select("input");
                    if (!inputs.isEmpty()) {
                        writer.println("\n输入框:");
                        for (Element input : inputs) {
                            writer.println("- 类型: " + input.attr("type"));
                            writer.println("  名称: " + input.attr("name"));
                            writer.println("  ID: " + input.attr("id"));
                            writer.println("  占位符: " + input.attr("placeholder"));
                        }
                    }
                    
                    // 记录按钮
                    Elements buttons = form.select("button, input[type=submit]");
                    if (!buttons.isEmpty()) {
                        writer.println("\n按钮:");
                        for (Element button : buttons) {
                            writer.println("- 类型: " + button.attr("type"));
                            writer.println("  名称: " + button.attr("name"));
                            writer.println("  值: " + button.attr("value"));
                            writer.println("  文本: " + button.text());
                        }
                    }
                }
            } else {
                writer.println("\n未发现表单");
            }
            
            // 记录登录相关元素
            writer.println("\n=== 登录相关元素 ===");
            
            // 检查登录按钮
            Elements loginButtons = doc.select("a[href*='login'], a[href*='Login'], " +
                                             "a[href*='signin'], a[href*='Signin'], " +
                                             "a[href*='认证'], a[href*='登录'], " +
                                             "button[onclick*='login'], button[onclick*='Login'], " +
                                             "button[onclick*='signin'], button[onclick*='Signin'], " +
                                             "button[onclick*='认证'], button[onclick*='登录']");
            if (!loginButtons.isEmpty()) {
                writer.println("\n登录按钮:");
                for (Element button : loginButtons) {
                    writer.println("- 标签: " + button.tagName());
                    writer.println("  文本: " + button.text());
                    writer.println("  HREF: " + button.attr("href"));
                    writer.println("  OnClick: " + button.attr("onclick"));
                }
            }
            
            // 检查登录提示
            Elements loginPrompts = doc.select("div.login-prompt, div.login-required, div.need-login, " +
                                             "div.login-tip, div.login-hint, div.login-notice, " +
                                             "div.login-reminder, div.login-warning, " +
                                             "div[class*='login'], div[class*='Login'], " +
                                             "div[class*='signin'], div[class*='Signin'], " +
                                             "div[class*='认证'], div[class*='登录'], " +
                                             "div[class*='auth'], div[class*='Auth']");
            if (!loginPrompts.isEmpty()) {
                writer.println("\n登录提示:");
                for (Element prompt : loginPrompts) {
                    writer.println("- 类名: " + prompt.attr("class"));
                    writer.println("  文本: " + prompt.text());
                }
            }
            
            // 记录页面源码
            writer.println("\n=== 页面源码 ===");
            writer.println(doc.html());
            
            System.out.println("\n登录信息已保存到文件: " + filename);
        } catch (IOException e) {
            System.err.println("保存登录信息失败: " + e.getMessage());
        }
    }

    /**
     * 记录登录失败页面
     * 职责：
     * 1. 保存登录失败时的页面HTML
     * 2. 记录失败原因和时间
     * 3. 保存页面截图（如果有）
     * 
     * @param domain 域名
     * @param url 登录页面URL
     * @param doc 页面文档
     * @param error 错误信息
     */
    public void recordLoginFailure(String domain, String url, Document doc, String error) {
        try {
            // 生成文件名：域名_时间戳.html
            String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String filename = String.format("%s_%s.html", domain, timestamp);
            File file = new File(LOGIN_FAIL_DIR, filename);
            
            // 保存页面HTML
            try (OutputStreamWriter writer = new OutputStreamWriter(
                new FileOutputStream(file), StandardCharsets.UTF_8)) {
                writer.write("<!-- 登录失败信息 -->\n");
                writer.write(String.format("<!-- 时间: %s -->\n", new Date()));
                writer.write(String.format("<!-- 域名: %s -->\n", domain));
                writer.write(String.format("<!-- URL: %s -->\n", url));
                writer.write(String.format("<!-- 错误: %s -->\n", error));
                writer.write("\n");
                writer.write(doc.html());
            }
            
            // 记录到日志
            String logMessage = String.format("登录失败 - 域名: %s, URL: %s, 错误: %s, 页面已保存到: %s",
                domain, url, error, file.getAbsolutePath());
            logger.error(logMessage);
            
        } catch (IOException e) {
            logger.error("保存登录失败页面时出错: {}", e.getMessage());
        }
    }

    /**
     * 检查是否需要登录
     * @param doc 页面文档
     * @param url 页面URL
     * @return 是否需要登录
     */
    public boolean needLogin(Document doc, String url) {
        System.out.println("\n=== 检查登录状态 ===");
        System.out.println("URL: " + url);
        
        // 1. 检查页面标题
        String title = doc.title().toLowerCase();
        if (title.contains("登录") || title.contains("login") || 
            title.contains("sign in") || title.contains("signin") ||
            title.contains("认证") || title.contains("auth")) {
            System.out.println("页面标题包含登录关键词");
            recordLoginInfo(doc, url);
            return true;
        }
        
        // 2. 检查 meta 标签
        Elements metaTags = doc.select("meta[name=description], meta[name=keywords]");
        for (Element meta : metaTags) {
            String content = meta.attr("content").toLowerCase();
            if (content.contains("登录") || content.contains("login") || 
                content.contains("sign in") || content.contains("signin") ||
                content.contains("认证") || content.contains("auth")) {
                System.out.println("Meta标签包含登录关键词");
                recordLoginInfo(doc, url);
                return true;
            }
        }
        
        // 3. 检查特定网站的登录页面特征
        if (url.contains("zhipin.com")) {
            // 检查 BOSS 直聘的登录页面特征
            Element pageKey = doc.select("#page_key_name").first();
            if (pageKey != null && pageKey.attr("value").contains("login")) {
                System.out.println("检测到 BOSS 直聘登录页面");
                recordLoginInfo(doc, url);
                return true;
            }
        }
        
        // 4. 检查登录表单
        Elements loginForms = doc.select("form[action*='login'], form[action*='Login'], " +
                                       "form[action*='signin'], form[action*='Signin'], " +
                                       "form[action*='auth'], form[action*='Auth'], " +
                                       "form[action*='认证'], form[action*='登录']");
        if (!loginForms.isEmpty()) {
            System.out.println("发现登录表单: " + loginForms.size() + " 个");
            recordLoginInfo(doc, url);
            return true;
        }
        
        // 5. 检查登录提示
        Elements loginPrompts = doc.select("div.login-prompt, div.login-required, div.need-login, " +
                                         "div.login-tip, div.login-hint, div.login-notice, " +
                                         "div.login-reminder, div.login-warning, " +
                                         "div[class*='login'], div[class*='Login'], " +
                                         "div[class*='signin'], div[class*='Signin'], " +
                                         "div[class*='认证'], div[class*='登录'], " +
                                         "div[class*='auth'], div[class*='Auth']");
        if (!loginPrompts.isEmpty()) {
            System.out.println("发现登录提示: " + loginPrompts.size() + " 个");
            recordLoginInfo(doc, url);
            return true;
        }
        
        // 6. 检查登录按钮
        Elements loginButtons = doc.select("button[type=submit], input[type=submit]");
        for (Element button : loginButtons) {
            String value = button.attr("value").toLowerCase();
            if (value.contains("登录") || value.contains("login") || 
                value.contains("sign in") || value.contains("signin") ||
                value.contains("认证") || value.contains("auth")) {
                System.out.println("发现登录按钮");
                recordLoginInfo(doc, url);
                return true;
            }
        }
        
        // 7. 检查页面内容
        String bodyText = doc.body().text().toLowerCase();
        if (bodyText.contains("请登录") || bodyText.contains("需要登录") || 
            bodyText.contains("请先登录") || bodyText.contains("登录后查看") ||
            bodyText.contains("登录后继续") || bodyText.contains("登录后操作")) {
            System.out.println("页面内容包含登录提示");
            recordLoginInfo(doc, url);
            return true;
        }
        
        // 8. 检查特定网站的登录状态
        if (url.contains("zhipin.com")) {
            // 检查 BOSS 直聘的登录状态
            Element loginStatus = doc.select("#header > div.header-nav > div.nav-item.login-item").first();
            if (loginStatus != null && loginStatus.text().contains("登录")) {
                System.out.println("检测到 BOSS 直聘未登录状态");
                recordLoginInfo(doc, url);
                return true;
            }
        }
        
        System.out.println("无需登录");
        return false;
    }

    /**
     * 执行登录
     */
    public boolean login(String domain) {
        System.out.println("\n=== 开始登录 ===");
        System.out.println("域名: " + domain);
        
        LoginConfig.LoginInfo loginInfo = loginConfig.getSites().get(domain);
        if (loginInfo == null) {
            System.out.println("未找到该域名的登录配置");
            System.out.println("请检查配置文件并添加登录信息");
            System.out.println("==================\n");
            return false;
        }

        // 使用默认值
        String usernameField = loginInfo.getUsernameField() != null ? 
            loginInfo.getUsernameField() : "username";
        String passwordField = loginInfo.getPasswordField() != null ? 
            loginInfo.getPasswordField() : "password";
        String submitButton = loginInfo.getSubmitButton() != null ? 
            loginInfo.getSubmitButton() : "submit";

        System.out.println("登录信息:");
        System.out.println("- 登录URL: " + loginInfo.getLoginUrl());
        System.out.println("- 用户名: " + loginInfo.getUsername());
        System.out.println("- 用户名字段: " + usernameField + " (默认值)");
        System.out.println("- 密码字段: " + passwordField + " (默认值)");
        System.out.println("- 提交按钮: " + submitButton + " (默认值)");

        try {
            System.out.println("正在发送登录请求...");
            Connection.Response response = Jsoup.connect(loginInfo.getLoginUrl())
                    .data(usernameField, loginInfo.getUsername())
                    .data(passwordField, loginInfo.getPassword())
                    .method(Connection.Method.POST)
                    .execute();

            Map<String, String> responseCookies = response.cookies();
            if (!responseCookies.isEmpty()) {
                System.out.println("登录成功，获取到Cookies:");
                responseCookies.forEach((key, value) -> 
                    System.out.println("- " + key + ": " + value));
                cookies.put(domain, responseCookies);
                System.out.println("==================\n");
                return true;
            } else {
                System.out.println("登录失败：未获取到Cookies");
                System.out.println("请检查登录配置是否正确");
                System.out.println("==================\n");
            }
        } catch (Exception e) {
            System.err.println("登录过程发生异常: " + e.getMessage());
            e.printStackTrace();
            System.out.println("==================\n");
        }
        return false;
    }

    /**
     * 获取登录后的cookies
     */
    public Map<String, String> getCookies(String domain) {
        System.out.println("\n=== 获取Cookies ===");
        System.out.println("域名: " + domain);
        
        Map<String, String> domainCookies = cookies.getOrDefault(domain, new HashMap<>());
        if (!domainCookies.isEmpty()) {
            System.out.println("当前Cookies:");
            domainCookies.forEach((key, value) -> 
                System.out.println("- " + key + ": " + value));
        } else {
            System.out.println("未找到该域名的Cookies");
        }
        System.out.println("==================\n");
        
        return domainCookies;
    }

    /**
     * 检查是否已登录
     */
    public boolean isLoggedIn(String domain) {
        System.out.println("\n=== 检查登录状态 ===");
        System.out.println("域名: " + domain);
        
        boolean isLoggedIn = cookies.containsKey(domain) && !cookies.get(domain).isEmpty();
        System.out.println("登录状态: " + (isLoggedIn ? "已登录" : "未登录"));
        System.out.println("==================\n");
        
        return isLoggedIn;
    }

    public void logout(String domain) {
        System.out.println("\n=== 执行登出 ===");
        System.out.println("域名: " + domain);
        
        if (cookies.remove(domain) != null) {
            System.out.println("登出成功");
        } else {
            System.out.println("该域名未登录");
        }
        System.out.println("==================\n");
    }
} 